home *** CD-ROM | disk | FTP | other *** search
- /*
- File: HighLevelTextConvert.c
-
- Contains: A Sample application for High-level text conversion
-
- Version: Technology: System 8
- Release: Daruma Developer Release 1
-
- Copyright: 1998 by Apple Computer, Inc., all rights reserved
-
- Contact: daruma@apple.com
-
- */
-
-
- #include "HighLevelTextConvert.h"
- #include "DebugUtil.h"
-
- #include <LanguageAnalysis.h>
- #include <JapaneseAnalysisEngine.h>
-
-
- //========================================================================================
- // Global variables
- //========================================================================================
- static LAContextRef gLastUsedContext = NULL;
-
- //========================================================================================
- // Prototypes for static functions
- //========================================================================================
- static OSStatus ConvertTextCommon( UInt16 conversionType, ByteCount inLength, const char *inTextBuf, ByteCount maxLength, ByteCount *outLength, char *outTextBuf );
- static OSStatus PrepareAnalysisContext( UInt16 conversionType, LAContextRef *context );
- static OSStatus InterpretBundleAsText( LAMorphemeBundle *bundle, ByteCount maxLength, ByteCount *outLength, void *outTextBuf );
- static OSStatus MapErrorCode( OSStatus originalError );
-
-
- /* =======================================================================================
- Routine: LaConvertPascalString (exported interface)
-
- Purpose: Convert specified pascal string
-
- Params: conversionType (in) : types of source text and destination
- inStr (in) : source pascal string
- outLength (out) : actual length of converted text
- outStr (out) : allocated buffer for converted pascal string
- ======================================================================================= */
- OSStatus
- LaConvertPascalString( UInt16 conversionType, ConstStr255Param inStr,
- ByteCount *outLength, Str255 outStr)
- {
- OSStatus err;
-
- err = ConvertTextCommon( conversionType, inStr[0], (char *)&inStr[1], 255, outLength, (char *)&outStr[1]);
- nrequire( err, convert_Failure);
-
- outStr[0] = ( *outLength > 255 ? 255 : (unsigned char)*outLength);
-
- return noErr;
-
- //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- convert_Failure:
- return MapErrorCode( err);
- }
-
-
- /* =======================================================================================
- Routine: LaConvertText (exported interface)
-
- Purpose: Convert specified text
-
- Params: conversionType (in) : types of source text and destination
- inLength (in) : length of source text
- inTextBuf (in) : buffer of source text
- maxLength (in) : size of allocated buffer for output
- outLength (out) : actual length of converted text
- outTextBuf (out) : allocated buffer for converted text
- ======================================================================================= */
- OSStatus
- LaConvertText( UInt16 conversionType, ByteCount inLength, const char *inTextBuf,
- ByteCount maxLength, ByteCount *outLength, char *outTextBuf )
- {
- OSStatus err;
-
- err = ConvertTextCommon( conversionType, inLength, inTextBuf, maxLength, outLength, outTextBuf);
- nrequire( err, convert_Failure);
-
- return noErr;
-
- //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- convert_Failure:
- return MapErrorCode( err);
- }
-
-
- /* =======================================================================================
- Routine: LaFinalizeConvert (exported interface)
-
- Purpose: Cleanup context
-
- Params: none
- ======================================================================================= */
- void
- LaFinalizeConvert( void)
- {
- if ( gLastUsedContext != NULL)
- LACloseContext( gLastUsedContext);
- }
-
-
- /* =======================================================================================
- Routine: ConvertTextCommon
-
- Purpose: Convert specified text
-
- Params: conversionType (in) : types of source text and destination
- inLength (in) : length of source text
- inTextBuf (in) : buffer of source text
- maxLength (in) : size of allocated buffer for output
- outLength (out) : actual length of converted text
- outTextBuf (out) : allocated buffer for converted text
- ======================================================================================= */
- static OSStatus
- ConvertTextCommon( UInt16 conversionType, ByteCount inLength, const char *inTextBuf,
- ByteCount maxLength, ByteCount *outLength, char *outTextBuf )
- {
- OSStatus err;
- LAContextRef context;
- LAMorphemePath *leadingEdge, *trailingEdge;
- LAMorphemeBundle analysisResult;
-
- require_action( inLength <= 255, tooLongText_Failure, err = kConvTextOverFlowErr;);
-
- err = PrepareAnalysisContext( conversionType, &context);
- nrequire( err, getContext_Failure);
-
- //------------------------------------------------------------
- // Batch analysis
- //
- leadingEdge = (LAMorphemePath *)kLADefaultEdge;
- trailingEdge = (LAMorphemePath *)kLADefaultEdge;
-
- err = LAMorphemeAnalysis( context, inTextBuf, inLength, leadingEdge, trailingEdge, 1, &analysisResult);
- nrequire( err, batchAnalysis_Failure);
-
- //------------------------------------------------------------
- // Get converted text
- //
- err = InterpretBundleAsText( &analysisResult, maxLength, outLength, outTextBuf);
- nrequire( err, getTextFromBundle_failure);
-
- //------------------------------------------------------------
- // Clean up
- //
- AEDisposeDesc( &analysisResult);
-
- return noErr;
-
- //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- getTextFromBundle_failure:
- AEDisposeDesc( &analysisResult);
- batchAnalysis_Failure:
- getContext_Failure:
- tooLongText_Failure:
- return err;
- }
-
-
- /* =======================================================================================
- Routine: PrepareAnalysisContext
-
- Purpose: If specified context is already opened, just returns it.
- If not, open a new context and returns it.
-
- Params: conversionType (in) : types of source text and destination
- context (out) : Daruma analysis context
- ======================================================================================= */
- static OSStatus
- PrepareAnalysisContext( UInt16 conversionType, LAContextRef *context )
- {
- static UInt16 gLastUsedConversionType = 0;
- OSStatus err, specificErr;
- LAEnvironmentRef environment;
- Str63 environmentName[3] = { kLAJapaneseKanaKanjiEnvironment,
- kLAJapaneseMorphemeAnalysisEnvironment,
- kLAJapaneseTTSEnvironment };
-
- //------------------------------------------------------------
- // Prepare analysis context if it is not opened yet.
- // (Last used context is cached)
- //
- if ( gLastUsedConversionType != conversionType)
- {
- switch ( conversionType)
- {
- case kConvertKanaToKanji:
- err = LAGetEnvironmentRef( environmentName[0], &environment);
- break;
-
- case kConvertKanjiToKana:
- err = LAGetEnvironmentRef( environmentName[1], &environment);
- break;
-
- case kConvertKanjiToUtterance:
- err = LAGetEnvironmentRef( environmentName[2], &environment);
- break;
-
- default:
- require_action( false, unknownType_failure, err = kConvUnknownConversionTypeErr;);
- break;
- }
- nrequire( err, getEnvironmentRef_Failure);
-
- //
- // Close old context (only one context is opened at a time)
- //
- if ( gLastUsedContext != NULL)
- {
- LACloseContext( gLastUsedContext);
- gLastUsedContext = NULL;
- }
-
- err = LAOpenContext( environment, &gLastUsedContext, &specificErr, NULL);
- nrequire( err, openContext_Failure);
-
- gLastUsedConversionType = conversionType;
- }
-
- *context = gLastUsedContext;
-
- return noErr;
-
- //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- openContext_Failure:
- gLastUsedConversionType = 0;
- *context = NULL;
- getEnvironmentRef_Failure:
- unknownType_failure:
- return err;
- }
-
-
- /* =======================================================================================
- Routine: InterpretBundleAsText
-
- Purpose: Gather converted text chunk in AERecord, and merge them into continuous text
-
- Params: bundle (in) : result AERecord returned by morpheme analysis
- maxLength (in) : size of allocated buffer for output
- outLength (out) : actual length of converted text
- outTextBuf (out) : allocated buffer for converted text
- ======================================================================================= */
- static OSStatus
- InterpretBundleAsText( LAMorphemeBundle *bundle, ByteCount maxLength,
- ByteCount *outLength, void *outTextBuf )
- {
- OSStatus err;
- long i, morphemeIndex;
- long morphemeNum;
- AEDescList morphemeNodeList = { typeNull, NULL};
- AEDescList morphemePathList = { typeNull, NULL};
- AEDescList morphemeIndexList = { typeNull, NULL};
- AERecord morphemePath = { typeNull, NULL};
- AERecord morpheme = { typeNull, NULL};
- AEDescList homographList = { typeNull, NULL};
- AERecord homograph = { typeNull, NULL};
- AEKeyword theAEKeyword;
- DescType typeCode;
- long actualSize;
- char *outTextPtr = (char *)outTextBuf;
- ByteCount totalLength = 0;
- Boolean hasOverflow = false;
-
- //------------------------------------------------------------
- // Get morpheme node list
- //
- err = AEGetKeyDesc( bundle, keyAELAMorpheme, typeAEList, &morphemeNodeList);
- nrequire( err, getMorphemeNodeList_failure);
-
- //------------------------------------------------------------------------------
- // Get morpheme path list
- //
- err = AEGetKeyDesc( bundle, keyAELAMorphemePath, typeAEList, &morphemePathList);
- nrequire( err, getMorphemePathList_failure);
-
- //------------------------------------------------------------
- // Get 1st morpheme path from morpheme path list
- //
- err = AEGetNthDesc( &morphemePathList, 1, typeAERecord, &theAEKeyword, &morphemePath);
- AEDisposeDesc( &morphemePathList);
- nrequire( err, getMorphemePath_failure);
-
- //------------------------------------------------------------
- // Get morpheme index list from morpheme path
- //
- err = AEGetKeyDesc( &morphemePath, keyAELAMorpheme, typeAEList, &morphemeIndexList);
- AEDisposeDesc( &morphemePath);
- nrequire( err, getMorphemeIndexList_failure);
-
- //------------------------------------------------------------
- // Count morpheme in the list
- //
- err = AECountItems( &morphemeIndexList, &morphemeNum);
- nrequire( err, countMorphemeNum_Failure);
-
- for ( i = 1; i <= morphemeNum; i++)
- {
- //------------------------------------------------------------
- // Get ith morpheme index from morpheme index list
- //
- err = AEGetNthPtr( &morphemeIndexList, i, typeInteger, &theAEKeyword, &typeCode,
- &morphemeIndex, sizeof(morphemeIndex), &actualSize);
- nrequire( err, getMorphemeIndex_Failure);
-
- //------------------------------------------------------------
- // Get morpheme node, specified by index, from morpheme node list
- //
- err = AEGetNthDesc( &morphemeNodeList, morphemeIndex, typeAERecord, &theAEKeyword, &morpheme);
- nrequire( err, getMorphemeNode_Failure);
-
- //------------------------------------------------------------
- // Get homograph list from morpheme node
- //
- err = AEGetKeyDesc( &morpheme, keyAELAHomograph, typeAEList, &homographList);
- AEDisposeDesc( &morpheme);
- nrequire( err, getHomographList_Failure);
-
- //------------------------------------------------------------------------------
- // Get 1st homograph node from homograph list
- //
- err = AEGetNthDesc( &homographList, 1, typeAERecord, &theAEKeyword, &homograph);
- AEDisposeDesc( &homographList);
- nrequire( err, getHomographNode_Failure);
-
- //------------------------------------------------------------------------------
- // Get data size of homograph text, and checks overflow
- //
- err = AESizeOfKeyDesc( &homograph, keyAEText, &typeCode, &actualSize);
- nrequire( err, getHomographDataSize_Failure);
-
- //
- // Even if the buffer is overflowed, the actual total text size should be returned
- //
- totalLength += actualSize;
-
- if ( !hasOverflow)
- {
- long tempMaxSize = actualSize;
-
- if ( totalLength > (long)maxLength)
- {
- hasOverflow = true;
- tempMaxSize = (long)maxLength - ( totalLength - actualSize);
- }
-
- //------------------------------------------------------------------------------
- // Get converted string from homograph node, and adds it to the end of buffer
- //
- err = AEGetKeyPtr( &homograph, keyAEText, typeChar, &typeCode, outTextPtr,
- tempMaxSize, &actualSize);
- nrequire( err, getHomographData_Failure);
-
- outTextPtr += tempMaxSize;
- }
-
- AEDisposeDesc( &homograph);
- }
-
- AEDisposeDesc( &morphemeNodeList);
- AEDisposeDesc( &morphemeIndexList);
-
- *outLength = (ByteCount)totalLength;
-
- return noErr;
-
- //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- getHomographData_Failure:
- getHomographDataSize_Failure:
- AEDisposeDesc( &homograph);
- getHomographNode_Failure:
- getHomographList_Failure:
- getMorphemeNode_Failure:
- getMorphemeIndex_Failure:
- countMorphemeNum_Failure:
- AEDisposeDesc( &morphemeIndexList);
- getMorphemeIndexList_failure:
- getMorphemePath_failure:
- getMorphemePathList_failure:
- AEDisposeDesc( &morphemeNodeList);
- getMorphemeNodeList_failure:
- return err;
- }
-
-
- /* =======================================================================================
- Routine: MapErrorCode
-
- Purpose: Maps internal error code to external one
-
- Params: originalError (in) : original (internal) error code
- ======================================================================================= */
- static OSStatus
- MapErrorCode( OSStatus originalError )
- {
- OSStatus resultError;
-
- switch ( originalError)
- {
- case laFailAnalysisErr:
- resultError = kConvFailAnalysisErr;
- break;
-
- case laTextOverFlowErr:
- resultError = kConvTextOverFlowErr;
- break;
-
- case fnfErr:
- case dcmBadDictionaryErr:
- case dcmNotDictionaryErr:
- resultError = kConvDictionaryNotFoundErr;
- break;
-
- default:
- resultError = originalError;
- break;
- }
-
- return resultError;
- }
-
-
-
-
-